﻿using System;
using System.Configuration;
using System.Text;
using System.Web;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Health;
using WebConfig = System.Web.Configuration;

namespace SPHealth.SharePoint.HealthRules.SP.Rules.Configuration
{
    public class WarnWebApplicationDebugMode : SPRepairableHealthAnalysisRule
    {
        #region Variables
        // Set some variables that are used to report bad web.config files and fire the rule
        private readonly StringBuilder _failingWebApps;
        private SPHealthAnalysisRuleAutomaticExecutionParameters _executionParameters;
        #endregion

        #region Rule Setup
        //The Summary for the rule
        public override string Summary
        {
            get { return "One or more Web Applications are in ASP.NET debug mode."; }
        }

        //The Explanation for the rule and what is not working
        public override string Explanation
        {
            get { return String.Format("The following web.config files are in ASP.NET debug mode:\r\n\r\n{0}", _failingWebApps); }
        }

        //How to fix the issue
        public override string Remedy
        {
            get { return "Disable the debug setting in the web.config file for the Web Application(s)."; }
        }

        //The type or error to flag this rule as
        public override SPHealthCheckErrorLevel ErrorLevel
        {
            get { return SPHealthCheckErrorLevel.Warning; }
        }

        //The category to store this rule under
        public override SPHealthCategory Category
        {
            get { return SPHealthCategory.Configuration; }
        }

        //public override string CustomCategory
        //{
        //    get { return "Todd's Health Rules"; }
        //    set { }
        //}
        #endregion

        #region Methods
        // constructor
        public WarnWebApplicationDebugMode()
        {
            _failingWebApps = new StringBuilder();
        }

        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                if (_executionParameters == null)
                {
                    _executionParameters = new SPHealthAnalysisRuleAutomaticExecutionParameters
                    {
                        Schedule = SPHealthCheckSchedule.Hourly,
                        Scope = SPHealthCheckScope.All,
                        ServiceType = typeof(SPTimerService),
                        RepairAutomatically = false
                    };
                }
                return _executionParameters;
            }
        }

        //The actual code that does the checks for the rule
        public override SPHealthCheckStatus Check()
        {
            //Check to see we can actually speak to the farm first
            if (!SPFarm.Joined)
            {
                throw new InvalidOperationException();
            }

            // assume all is good - innocent until proved guilty...
            SPHealthCheckStatus status = SPHealthCheckStatus.Passed;

            //Loop through all Web Apps to get all IIS settings
            foreach (SPWebApplication webApplication in SPWebService.ContentService.WebApplications)
            {
                //For each Web App, take the IIS settings and append the path of the App to the root location
                SPIisSettings iis = webApplication.IisSettings[SPUrlZone.Default];
                string path = "/wss/VirtualDirectories/" + iis.Path.Name;

                //Grab the web.config for each Web App
                System.Configuration.Configuration webConfig = WebConfig.WebConfigurationManager.OpenWebConfiguration("/",webApplication.Name);
                System.Web.Configuration.SystemWebSectionGroup systemWeb = webConfig.GetSectionGroup("system.web") as System.Web.Configuration.SystemWebSectionGroup;

                try
                {
                    if (systemWeb.Compilation.Debug)
                    {
                        _failingWebApps.Append(String.Format("{0} on server {1} - '{2}\\web.config'\r\n\r\n", webApplication.Name, Environment.MachineName,  iis.Path.FullName));
                    }
                }
                catch (Exception ex)
                {
                    _failingWebApps.Append(String.Format("'{0}\\web.config' - Unable to verify web.config file ({1})\r\n\r\n", iis.Path.FullName, ex.Message));
                }
            }

            if (_failingWebApps.ToString().Length > 0)
                status = SPHealthCheckStatus.Failed;

            return status;
        }

        //The code that performs automatic repair
        public override SPHealthRepairStatus Repair()
        {
            //Set the status of the rule to succeeded
            SPHealthRepairStatus status = SPHealthRepairStatus.Succeeded;

            //Loop through all Web Apps to get all IIS settings
            foreach (SPWebApplication webApplication in SPWebService.ContentService.WebApplications)
            {
                //For each Web App, take the IIS settings and append the path of the App to the root location
                SPIisSettings iis = webApplication.IisSettings[SPUrlZone.Default];
                string path = "/wss/VirtualDirectories/" + iis.Path.Name;

                //Grab the web.config for each Web App
                System.Configuration.Configuration webConfig = WebConfig.WebConfigurationManager.OpenWebConfiguration("/", webApplication.Name);
                System.Web.Configuration.SystemWebSectionGroup systemWeb = webConfig.GetSectionGroup("system.web") as System.Web.Configuration.SystemWebSectionGroup;


                if (systemWeb.Compilation.Debug)
                {
                    try
                    {
                        // update the complication value
                        systemWeb.Compilation.Debug = false;
                        webConfig.Save(ConfigurationSaveMode.Modified, true);
                    }
                    catch
                    {
                        //If it fails catch the exception and set the repair status to failed, but keep on trying
                        status = SPHealthRepairStatus.Failed;
                    }
                }
            }

            //Return the succeeded status to clear the rule
            return status;
        }
        #endregion
    }
}
